package models

import (
	"context"                          // 导入上下文包
	"go.mongodb.org/mongo-driver/bson" // 导入BSON包，用于MongoDB查询
	"log"
)

// UserBasic 用户基本信息模型
type UserBasic struct {
	// 直接定义Identity字段以确保正确映射MongoDB的_id 导出Base 模型会导致 bson 映射失败
	Identity  string `bson:"identity" json:"identity"`     // 唯一标识
	CreatedAt int64  `bson:"created_at" json:"created_at"` // 创建时间戳
	UpdatedAt int64  `bson:"updated_at" json:"updated_at"` // 更新时间戳
	Account   string `bson:"account" json:"account"`       // 用户账号
	Password  string `bson:"password" json:"password"`     // 用户密码（MD5加密存储）
	Nickname  string `bson:"nickname" json:"nickname"`     // 用户昵称
	Sex       int    `bson:"sex" json:"sex"`               // 性别：0-未知 1-男 2-女
	Email     string `bson:"email" json:"email"`           // 邮箱地址
	Avatar    string `bson:"avatar" json:"avatar"`         // 头像URL
}

// CollectionName 获取用户基本信息的集合名称
func (UserBasic) CollectionName() string {
	return "user_basic" // 指定MongoDB集合名称为user_basic
}

// GetUserBasicByAccountPassword 根据账号和密码查询用户信息
func GetUserBasicByAccountPassword(account, password string) (*UserBasic, error) {
	ub := &UserBasic{} // 创建UserBasic结构体实例，用于存储查询结果

	// 在MongoDB中查询匹配账号密码的用户记录 // 获取用户集合
	err := Mongo.Collection(UserBasic{}.CollectionName()).
		FindOne(context.Background(), bson.M{ // 使用FindOne方法查询单条记录
			"account":  account,  // 查询条件：账号
			"password": password, // 查询条件：密码
		}).Decode(ub) // 将查询结果解码到ub结构体中

	return ub, err // 返回用户信息和可能的错误
}

// GetUserBasicByIdentity 根据用户ID查询用户基本信息
func GetUserBasicByIdentity(identity string) (*UserBasic, error) {
	ub := &UserBasic{} // 创建UserBasic结构体实例，用于存储查询结果
	// MongoDB查询：根据 Identity 字段查找用户
	err := Mongo.Collection(UserBasic{}.CollectionName()).
		FindOne(context.Background(), bson.M{"identity": identity}).
		Decode(ub)

	return ub, err // 返回用户信息和可能的错误
}

// GetUserBasicByAccount 根据 账号 查询用户基本信息
func GetUserBasicByAccount(account string) (*UserBasic, error) {
	ub := &UserBasic{} // 创建用户基础信息结构体指针

	// 在MongoDB中查询指定账号的用户信息
	err := Mongo.Collection(UserBasic{}.CollectionName()).
		FindOne(context.Background(), bson.D{
			{"account", account}, // 查询条件：账号匹配
		}).Decode(ub) // 将查询结果解码到结构体

	return ub, err // 返回用户信息和错误（如果有）
}

// GetUserBasicCountByEmail 根据邮箱统计用户数量
func GetUserBasicCountByEmail(email string) (int64, error) {
	// 执行MongoDB查询：统计指定邮箱的用户数量
	return Mongo.Collection(UserBasic{}.CollectionName()).
		CountDocuments(context.Background(), bson.D{
			{"email", email}, // 查询条件：email字段匹配
		})
}

// GetUserBasicCountByAccount 根据账号统计用户数量的函数
func GetUserBasicCountByAccount(account string) (int64, error) {
	// 调用MongoDB的CountDocuments方法统计符合条件的文档数量
	return Mongo.Collection(UserBasic{}.CollectionName()).
		CountDocuments(
			context.Background(), // 使用背景上下文
			bson.D{
				{"account", account}, // 查询条件：账号字段匹配
			},
		)
}

// InsertOneUserBasic 插入单个用户基础信息到MongoDB
func InsertOneUserBasic(ub *UserBasic) error {
	// 获取用户基础信息集合，并执行插入操作
	_, err := Mongo.Collection(UserBasic{}.CollectionName()).InsertOne(context.Background(), ub)
	return err // 返回操作结果（成功为nil，失败为错误信息）
}

// JudgeUserIsFriend 判断两个用户是否为好友关系
func JudgeUserIsFriend(userIdentity1, userIdentity2 string) bool {
	// 查询用户所在的单聊房间列表
	cursor, err := Mongo.Collection(UserRoom{}.CollectionName()).
		Find(context.Background(), bson.D{
			{"user_identity", userIdentity1}, // 条件1：用户标识匹配
			{"room_type", 1},                 // 条件2：房间类型为单聊(1)
		})
	if err != nil { // 错误处理：判断操作是否发生错误
		log.Printf("[DB ERROR]:%v\n", err) // 记录错误日志到控制台，包含详细错误信息
		return false                       // 返回操作失败状态和错误对象
	}

	var roomIdentities []string // 声明字符串切片，用于存储用户所在的单聊房间标识列表

	// 遍历查询结果游标
	for cursor.Next(context.Background()) {
		ur := new(UserRoom)      // 创建新的用户房间对象
		err := cursor.Decode(ur) // 将MongoDB文档解码到结构体
		if err != nil {          // 解码失败处理
			log.Printf("[Dcode ERROR]:%v \n", err) // 打印错误日志
			return false                           // 返回错误，终止函数
		}
		roomIdentities = append(roomIdentities, ur.RoomIdentity) // 收集房间标识
	}

	// 获取关联 userIdentity2 的单聊房间个数
	cnt, err := Mongo.Collection(UserRoom{}.CollectionName()).
		CountDocuments(context.Background(), bson.M{
			"user_identity": userIdentity2,                 // 条件1：用户标识匹配userIdentity2
			"room_identity": bson.M{"$in": roomIdentities}, // 条件2：房间标识在userIdentity1的房间列表中
		})
	if err != nil { // 检查数据库操作是否出错
		log.Printf("[DB ERROR]:%v \n", err) // 打印错误日志
		return false
	}
	if cnt > 0 { // 检查共同房间数量是否大于0
		return true // 存在共同房间，判定为好友关系
	}

	return false // 返回失败状态
}

func GetUserRoomIdentity(userIdentity1, userIdentity2 string) string {
	// 查询用户所在的单聊房间列表
	cursor, err := Mongo.Collection(UserRoom{}.CollectionName()).
		Find(context.Background(), bson.D{
			{"user_identity", userIdentity1}, // 条件1：用户标识匹配
			{"room_type", 1},                 // 条件2：房间类型为单聊(1)
		})
	if err != nil { // 错误处理：判断操作是否发生错误
		log.Printf("[DB ERROR]:%v\n", err) // 记录错误日志到控制台，包含详细错误信息
		return ""
	}

	var roomIdentities []string // 声明字符串切片，用于存储用户所在的单聊房间标识列表

	// 遍历查询结果游标
	for cursor.Next(context.Background()) {
		ur := new(UserRoom)      // 创建新的用户房间对象
		err := cursor.Decode(ur) // 将MongoDB文档解码到结构体
		if err != nil {          // 解码失败处理
			log.Printf("[Dcode ERROR]:%v \n", err) // 打印错误日志
			return ""
		}
		roomIdentities = append(roomIdentities, ur.RoomIdentity) // 收集房间标识
	}

	ur := &UserRoom{} // 创建用户房间对象
	// 获取关联 userIdentity2 的单聊房间个数
	err = Mongo.Collection(UserRoom{}.CollectionName()).
		FindOne(context.Background(), bson.M{
			"user_identity": userIdentity2,                 // 目标用户标识
			"room_identity": bson.M{"$in": roomIdentities}, // 在用户1的房间列表中查找
		}).Decode(ur) // 将查询结果解码到结构体

	if err != nil {
		log.Printf("[DB ERROR]:%v \n", err) // 记录查询错误
		return ""
	}
	return ur.RoomIdentity // 返回找到的房间标识
}

// DeleteUserRoom 根据房间标识删除用户房间关联记录
func DeleteUserRoom(roomIdentity string) error {
	// 在MongoDB的用户房间集合中删除指定房间的所有关联记录
	_, err := Mongo.Collection(UserRoom{}.CollectionName()).
		DeleteOne(context.Background(), bson.M{"room_identity": roomIdentity})

	// 检查删除操作是否出错
	if err != nil {
		log.Printf("[DB ERROR]:%v\n", err) // 记录数据库错误日志
		return err
	}

	return nil // 删除成功，返回nil
}
